#include "list.h"
#include "console.h"

void list_init(list_t *li) {
    li->head = 0;
    li->tail = 0;
}

void list_node_init(list_node_t *node) {
    node->next = 0;
    node->prev = 0;
}

int list_empty(list_t *li) {
    return li->head == 0;
}

int list_single(list_t *li) {
    return li->head == li->tail;
}

void list_push_front(list_t *li, list_node_t *x) {
    assert(x->next == 0);
    assert(x->prev == 0);

    x->next = li->head;
    if (li->head)
        li->head->prev = x;

    li->head = x;
    if (!li->tail)
        li->tail = x;
}

void list_push_back(list_t *li, list_node_t *x) {
    assert(x->next == 0);
    assert(x->prev == 0);

    x->prev = li->tail;
    if (li->tail)
        li->tail->next = x;

    li->tail = x;
    if (!li->head)
        li->head = x;
}

void list_pop_front(list_t *li) {
    assert(li->head != 0);

    list_node_t *x = li->head;
    li->head = x->next;
    if (x == li->tail)
        li->tail = 0;
    else {
        x->next->prev = 0;
        x->next = 0;
    }
}

void list_pop_back(list_t *li) {
    assert(li->tail != 0);

    list_node_t *x = li->tail;
    li->tail = x->prev;
    if (x == li->head)
        li->head = 0;
    else {
        x->prev->next = 0;
        x->prev = 0;
    }
}

void list_remove(list_t *li, list_node_t *node) {
    if (node->prev)
        node->prev->next = node->next;
    if (node->next)
        node->next->prev = node->prev;

    if (li->head == node)
        li->head = node->next;
    if (li->tail == node)
        li->tail = node->prev;

    node->next = 0;
    node->prev = 0;
}